home *** CD-ROM | disk | FTP | other *** search
/ Computer Music Interactif…cial Edition 1999 Winter / cd 3.iso / mac / Mac / Shares / Midishare™1.68 / Development Tools / Smalltalk / st80-midi.c < prev   
Encoding:
C/C++ Source or Header  |  1995-10-10  |  36.3 KB  |  1,642 lines  |  [TEXT/MPS ]

  1. /********************************************************************************/
  2. /*                     Smalltalk\Objectworks R4.1 Midi Primitives                    */
  3. /*        Macintosh System7, GRAME's MidiShare™ and optional Apple's MidiManager    */
  4. /*                        André Ch. Schnoor, Hamburg (Germany)                    */
  5. /*                  czesanne@mail.hh.provi.de, czesanne@proaudio.de                */
  6. /*                                                                              */
  7. /*  The following features were included:                                       */
  8. /*    1) Sequencer-like in/out/start/stop/tempo etc. features                   */
  9. /*    2) Bridge to the Apple MidiManager                                        */
  10. /*                                                                              */
  11. /*  The MidiManager™ Bridge is partially © GRAME 1991, Yann Orlarey (msPass)    */
  12. /********************************************************************************/
  13.  
  14. #include "userprim.h"
  15. #include <MIDI.h>
  16. #include <Resources.h>
  17. #include "MidiShare.h"
  18.  
  19. /********************************************************************************/
  20. /*                                 Declarations and Prototypes                        */
  21. /********************************************************************************/
  22.                                             
  23. #define        ports 10                        // Total of all ports (incl. MidiManager)
  24. #define        midiManagerPort0 9                // Global port used for MidiManager Out0
  25. #define        midiManagerPort1 10                // Global port used for MidiManager Out1
  26.  
  27. unsigned     long    preroll        = 2000;        // Delay (ms) before playing
  28. unsigned     long    start         = 0;        // Time offset (midi ticks)
  29. unsigned     long    offset         = 0;        // Time offset (ms)
  30. float                tempo         = 120;        // Tempo setting for ms-calculation
  31. float                resolution     = 1920;        // Resolution (midi ticks p. 4/4)
  32.  
  33. /********************************************************************************/
  34. /*                                 GRAME's MidiShare                                */
  35. /********************************************************************************/
  36. #define         midiShareRefName     "\pSmalltalk™"
  37. #define        midiShareBridgeName "\pSt-Bridge"
  38. #define        midiShareLinkName    "\pSt-Link"
  39.  
  40. short        midiShareRef = 0;                // MidiShare™ ref. for phys. output
  41. short         midiShareLink = 0;                // MidiShare™ ref. for linking MidiManager
  42. short        midiShareBridge = 0;            // MidiShare™ ref. attached to MidiManager
  43.  
  44. /********************************************************************************/
  45. /*                                 Apple's MidiManager                                */
  46. /********************************************************************************/
  47. #define     appName             "\pSmalltalk-80™"
  48. #define     appID                'ST8M'
  49.  
  50. short        midiManagerRefOut [2];            // port handles for output
  51. short        midiManagerRefIn  [2];             // port handles for input
  52. short        midiManagerTime;                // port for time sync
  53.  
  54. Boolean        bridgeInstalled = false;        // MidiShare => MidiManager?
  55.  
  56. /********************************************************************************/
  57. /*                                                                                 */
  58. /********************************************************************************/
  59.  
  60. #define timePortBuffSize    256L
  61. #define inputPortBuffSize    2048L
  62. #define outputPortBuffSize    256L
  63.  
  64. /********************************************************************************/
  65. /*                                     Functions                                    */
  66. /********************************************************************************/
  67.  
  68. Boolean        MidiSystemOpen  ();              // Install all available Midi features
  69. Boolean      MidiSystemStop  ();                 // Stop playing
  70. Boolean      MidiSystemClose ();                 // Uninstall everything
  71.  
  72. Boolean     MidiBridgeClose ();
  73.  
  74. long ms     ( long ticks );                    // Convert ticks->clock according current tempo/res.
  75. long ticks     ( long ms );                    // Convert vice versa
  76.  
  77. void Send         ( MidiEvPtr e );            // Send MidiShare Event at designated time
  78. void Sequence     ( MidiEvPtr e );            // Send event to sequencer queue
  79. void SendNow     ( MidiEvPtr e );            // Send event immediately
  80.  
  81. void SendAllNotesOff ( 
  82.     long clock, 
  83.     int port, 
  84.     int chan);
  85.     
  86. void SendNoteEvent ( 
  87.     long clock, 
  88.     int port, 
  89.     int chan, 
  90.     int pitch, 
  91.     int vel, 
  92.     int dur);
  93.  
  94. void SendControlEvent ( 
  95.     long clock, 
  96.     int port, 
  97.     int chan, 
  98.     int controller, 
  99.     int value);
  100.  
  101. void SendProgramEvent ( 
  102.     long clock, 
  103.     int port, 
  104.     int chan, 
  105.     int program);
  106.  
  107. /********************************************************************************/
  108. /*                                     Sequencer                                    */
  109. /********************************************************************************/
  110.  
  111. #define     idle         0
  112. #define     playing     1
  113.  
  114. short        sequencerState = idle;
  115. MidiSeqPtr    sequence;
  116. MidiEvPtr    sequenceTask;
  117.  
  118. void OpenSequencer ()
  119. {
  120.     sequencerState = idle;                        // first state is idle
  121.     sequence = MidiNewSeq();                    // create an empty sequence
  122.     sequenceTask = 0;                            // no task at the momment
  123. }
  124.  
  125.  
  126. void StopSequencer ()
  127. {
  128.     switch (sequencerState) {
  129.         case playing :                            // stop playing
  130.             MidiForgetTask(&sequenceTask);        // forget the current play task
  131.             sequencerState = idle;
  132.             MidiClearSeq(sequence);                // clear sequence contents
  133.             break;
  134.             
  135.         case idle :    
  136.             MidiClearSeq(sequence);                // clear sequence contents                        
  137.             break;
  138.     }
  139. }
  140.  
  141. void CloseSequencer ()                
  142. {
  143.     StopSequencer();                            // stop current activities
  144.     MidiFreeSeq(sequence);                        // free the sequence
  145. }
  146.  
  147.  
  148. pascal void    PlayTask (long date, short refNum, MidiEvPtr e, long d, long unused )
  149. {
  150.     d = Date(e);                                        // remember the date of the current event to play
  151.     while (e && (Date(e) == d)) {                        // for all the events at this date
  152.         SendNow(MidiCopyEv(e));        
  153.         e = Link(e);                                    // go to next event
  154.     };
  155.     
  156.     if (e) {                                            // if not the end, schedule the task for next event
  157.         sequenceTask = MidiTask(
  158.             (TaskPtr)PlayTask, 
  159.             date + Date(e) - d, 
  160.             refNum, 
  161.             (long)e, 
  162.             0,
  163.             0);
  164.             
  165.     } else {
  166.         sequencerState = idle;
  167.         sequenceTask = 0;
  168.     }
  169. }
  170.  
  171.  
  172. Boolean StartSequencer ()
  173. {
  174.     MidiEvPtr e;
  175.     
  176.     if (sequencerState == playing) return false;
  177.                                               
  178.     if (e = First(sequence)) {                            
  179.         sequencerState = playing;                        
  180.         PlayTask(MidiGetTime(), midiShareRef, e, 0, 0);         
  181.     };
  182.     return true;
  183. }
  184.  
  185. /********************************************************************************/
  186. /*                                                                                 */
  187. /********************************************************************************/
  188.  
  189. typedef struct TScanner * ScannerPtr;        // Scanner for SYSEX streams
  190. typedef struct TScanner
  191. {
  192.     long        length;
  193.     MidiSEXPtr    block;
  194.     long        pos;
  195.     int            index;
  196. } TScanner;
  197.  
  198. typedef struct TFormatter * FormatterPtr;    // Formatter for SYSEX streams
  199. typedef struct TFormatter
  200. {
  201.     long        num;                        // numéro du packet courant (à partir de 0)
  202.     int            index;                        // index dans le packet courant [0..248]
  203.     short        port;                        // refnum du port MidiManager
  204.     MIDIPacket    packet;                        // packet MidiManager
  205. } TFormatter;
  206.         
  207. TFilter        myFilter;                        // filtre pour les événements Midi
  208. MidiEvPtr    PendingEv[2];                    // Evénements en cours de construction
  209.  
  210. /********************************************************************************/
  211. /*                                 Conversion Tables                                */
  212. /********************************************************************************/
  213.  
  214. typedef void     (* ms2mmfp) (MidiEvPtr e);    // MidiShare events ==> MidiManager packets
  215. ms2mmfp            ms2mmtbl[256];
  216.  
  217. typedef void     (* mm2msfp) (MIDIPacket * m, short port, short chan);
  218. mm2msfp            mm2mstbl[8];                // MidiManager packets ==> MidiShare events
  219.  
  220. typedef void     (* rt2msfp) (MIDIPacket * m, short port);
  221. rt2msfp            rt2mstbl[16];
  222.  
  223. /********************************************************************************/
  224. /*                                 String Operations                                */
  225. /********************************************************************************/
  226.  
  227. void InsertCh( Str255 s, short p, char c)        /* Insert un caractère dans une
  228. chaine Pascal    */
  229. {                                                /* à partir de la position p (de 1 à n).        */
  230.     register short n;        
  231.     register char t;
  232.         
  233.     if (p >= s[0])
  234.         s[s[0]] = c;
  235.     else
  236.         for (n= s[0]-p; n>=0; n--, p++) { t=c; c=s[p]; s[p]=t; }
  237.     s[0]++;
  238. }
  239.  
  240. void ShiftPStr( Str255 s, short n )                /* Décale une chaine Pascal de n
  241. caractères      */
  242. {                                                /* vers la droite.                                 */
  243.     register char *ps;
  244.     register char *pd;
  245.     
  246.     ps = (char*)s + s[0];
  247.     pd = ps + n;
  248.     s[0] += n;
  249.     for (; n>0; n--) *pd-- = *ps-- ;
  250. }
  251.  
  252. void TransfPStr(Str255 s1, char* s2, short n)    /* Ecrase le début de la
  253. chaine s1 avec s2         */
  254. {
  255.     for (; n>0; n--) *++s1 = *++s2 ;
  256. }
  257.  
  258. void AddFirst( Str255 s1, char * s2)            /* Insere en début de la chaine s1
  259. la chaine s2    */
  260. {
  261.     ShiftPStr( s1, s2[0] );
  262.     TransfPStr( s1, s2, s2[0] );
  263. }
  264.  
  265. void myC2PStr ( char* cs, Str255 ps)
  266. {
  267.     int    i;
  268.     
  269.     for (i=0; cs[i]; i++) ps[i+1] = cs[i];
  270.     ps[0] = i;
  271. }
  272.  
  273. /********************************************************************************/
  274. /*                                                                                 */
  275. /********************************************************************************/
  276.  
  277. void InitFormat (FormatterPtr f, short p)
  278. {
  279.     f->num = 0; f->index = 0; f->port = p;
  280. }
  281.  
  282. void Format (FormatterPtr f, short v)
  283. {
  284.     if (f->index > 248) {
  285.         if (f->num == 0)
  286.             f->packet.flags = midiTimeStampCurrent | midiStartCont;
  287.         else
  288.             f->packet.flags = midiTimeStampCurrent | midiMidCont;
  289.         f->packet.len = 255;
  290.         MIDIWritePacket( f->port, &(f->packet) );
  291.         f->index = 0;
  292.         f->num++;
  293.     }
  294.     f->packet.data[f->index] = v;
  295.     f->index++;
  296. }
  297.  
  298. void StopFormat (FormatterPtr f)
  299. {
  300.     f->packet.len = f->index + 6;
  301.     if (f->num == 0)
  302.         f->packet.flags = midiTimeStampCurrent | midiNoCont;
  303.     else
  304.         f->packet.flags = midiTimeStampCurrent | midiEndCont;
  305.     MIDIWritePacket( f->port, &(f->packet) );
  306. }
  307.  
  308.  
  309. /********************************************************************************/
  310. /*                                                                                 */
  311. /********************************************************************************/
  312.  
  313. long    InitScanner (ScannerPtr s, MidiEvPtr e)
  314. {
  315.     s->length     = MidiCountFields(e);
  316.     s->pos        = 0;
  317.     s->index    = 0;
  318.     s->block    = Link(LinkSE(e));
  319.     return s->length;
  320. }
  321.  
  322. long    RemainToScan (ScannerPtr s)
  323. {
  324.     if (s->pos < s->length)
  325.         return s->length - s->pos;
  326.     else
  327.         return 0;
  328. }
  329.  
  330. int Scan (ScannerPtr s)
  331. {
  332.     int        b;
  333.     
  334.     if (s->pos >= s->length) return -1;
  335.     b = s->block->data[s->index];
  336.     s->pos++;
  337.     s->index++;
  338.     if (s->index >= 12) {
  339.         s->index = 0;
  340.         s->block = Link(s->block);
  341.     }
  342.     return b;
  343. }
  344.     
  345. /********************************************************************************/
  346. /*                                                                                 */
  347. /********************************************************************************/
  348.  
  349. void SendNothing (MidiEvPtr e)
  350. {
  351.     MidiFreeEv(e);
  352. }
  353.  
  354.  
  355. void SendKeyOn (MidiEvPtr e)
  356. {
  357.     MIDIPacket    TheMIDIPacket;
  358.     
  359.     TheMIDIPacket.flags = 0x80;    
  360.     TheMIDIPacket.len = 9;
  361.     
  362. // send note on.
  363.     TheMIDIPacket.data[0] = Chan(e) + NoteOn;
  364.     TheMIDIPacket.data[1] = Pitch(e);
  365.     TheMIDIPacket.data[2] = Vel(e);
  366.     MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
  367.     
  368.     MidiFreeEv(e);
  369. }
  370.  
  371.  
  372. void SendKeyOff (MidiEvPtr e)
  373. {
  374.     MIDIPacket    TheMIDIPacket;
  375.     
  376.     TheMIDIPacket.flags = 0x80;    
  377.     TheMIDIPacket.len = 9;
  378.     
  379. // send note off.
  380.     TheMIDIPacket.data[0] = Chan(e) + NoteOff;
  381.     TheMIDIPacket.data[1] = Pitch(e);
  382.     TheMIDIPacket.data[2] = Vel(e);
  383.     MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
  384.     
  385.     MidiFreeEv(e);
  386. }
  387.  
  388.  
  389. void SendNote (MidiEvPtr e)
  390. {
  391.     MIDIPacket    TheMIDIPacket;
  392.     
  393.     TheMIDIPacket.flags = 0x80;    
  394.     TheMIDIPacket.len = 9;
  395.     
  396. // send note on.
  397.     TheMIDIPacket.data[0] = Chan(e) + NoteOn;
  398.     TheMIDIPacket.data[1] = Pitch(e);
  399.     TheMIDIPacket.data[2] = Vel(e);
  400.     MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
  401.     
  402. // transform e into a note off.
  403.     EvType(e) = typeKeyOff;  // has been typeKeyOn!
  404.     Date(e) += Dur(e);
  405.     Vel(e) = 0;
  406.     MidiSend(midiShareBridge+128, e);
  407. }
  408.  
  409.  
  410. void SendKeyPress (MidiEvPtr e)
  411. {
  412.     MIDIPacket    TheMIDIPacket;
  413.     
  414.     TheMIDIPacket.flags = 0x80;    
  415.     TheMIDIPacket.len = 9;
  416.     TheMIDIPacket.data[0] = Chan(e) + PolyTouch;
  417.     TheMIDIPacket.data[1] = Pitch(e);
  418.     TheMIDIPacket.data[2] = Vel(e);
  419.     MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
  420.     
  421.     MidiFreeEv(e);
  422. }
  423.  
  424.  
  425. void SendCtrlChange (MidiEvPtr e)
  426. {
  427.     MIDIPacket    TheMIDIPacket;
  428.     
  429.     TheMIDIPacket.flags = 0x80;    
  430.     TheMIDIPacket.len = 9;
  431.     TheMIDIPacket.data[0] = Chan(e) + ControlChg;
  432.     TheMIDIPacket.data[1] = Pitch(e);
  433.     TheMIDIPacket.data[2] = Vel(e);
  434.     MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
  435.     
  436.     MidiFreeEv(e);
  437. }
  438.  
  439.  
  440. void SendProgChange (MidiEvPtr e)
  441. {
  442.     MIDIPacket    TheMIDIPacket;
  443.     
  444.     TheMIDIPacket.flags = 0x80;    
  445.     TheMIDIPacket.len = 8;
  446.     TheMIDIPacket.data[0] = Chan(e) + ProgramChg;
  447.     TheMIDIPacket.data[1] = Pitch(e);
  448.     MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
  449.     
  450.     MidiFreeEv(e);
  451. }
  452.  
  453.  
  454. void SendChanPress (MidiEvPtr e)
  455. {
  456.     MIDIPacket    TheMIDIPacket;
  457.     
  458.     TheMIDIPacket.flags = 0x80;    
  459.     TheMIDIPacket.len = 8;
  460.     TheMIDIPacket.data[0] = Chan(e) + AfterTouch;
  461.     TheMIDIPacket.data[1] = Pitch(e);
  462.     MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
  463.     
  464.     MidiFreeEv(e);
  465. }
  466.  
  467.  
  468. void SendPitchWheel (MidiEvPtr e)
  469. {
  470.     MIDIPacket    TheMIDIPacket;
  471.     
  472.     TheMIDIPacket.flags = 0x80;    
  473.     TheMIDIPacket.len = 9;
  474.     TheMIDIPacket.data[0] = Chan(e) + PitchBend;
  475.     TheMIDIPacket.data[1] = Pitch(e);
  476.     TheMIDIPacket.data[2] = Vel(e);
  477.     MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
  478.     
  479.     MidiFreeEv(e);
  480. }
  481.  
  482.  
  483. void SendSongPos (MidiEvPtr e)
  484. {
  485.     MIDIPacket    TheMIDIPacket;
  486.     
  487.     TheMIDIPacket.flags = 0x80;    
  488.     TheMIDIPacket.len = 9;
  489.     TheMIDIPacket.data[0] = SongPos;
  490.     TheMIDIPacket.data[1] = Pitch(e);
  491.     TheMIDIPacket.data[2] = Vel(e);
  492.     MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
  493.     
  494.     MidiFreeEv(e);
  495. }
  496.  
  497.  
  498. void SendSongSel (MidiEvPtr e)
  499. {
  500.     MIDIPacket    TheMIDIPacket;
  501.     
  502.     TheMIDIPacket.flags = 0x80;    
  503.     TheMIDIPacket.len = 8;
  504.     TheMIDIPacket.data[0] = SongSel;
  505.     TheMIDIPacket.data[1] = Pitch(e);
  506.     MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
  507.     
  508.     MidiFreeEv(e);
  509. }
  510.  
  511.  
  512. void SendClock (MidiEvPtr e)
  513. {
  514.     MIDIPacket    TheMIDIPacket;
  515.     
  516.     TheMIDIPacket.flags = 0x80;    
  517.     TheMIDIPacket.len = 7;
  518.     TheMIDIPacket.data[0] = MClock;
  519.     MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
  520.     
  521.     MidiFreeEv(e);
  522. }
  523.  
  524.  
  525. void SendStart (MidiEvPtr e)
  526. {
  527.     MIDIPacket    TheMIDIPacket;
  528.     
  529.     TheMIDIPacket.flags = 0x80;    
  530.     TheMIDIPacket.len = 7;
  531.     TheMIDIPacket.data[0] = MStart;
  532.     MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
  533.     
  534.     MidiFreeEv(e);
  535. }
  536.  
  537.  
  538. void SendContinue (MidiEvPtr e)
  539. {
  540.     MIDIPacket    TheMIDIPacket;
  541.     
  542.     TheMIDIPacket.flags = 0x80;    
  543.     TheMIDIPacket.len = 7;
  544.     TheMIDIPacket.data[0] = MCont;
  545.     MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
  546.     
  547.     MidiFreeEv(e);
  548. }
  549.  
  550.  
  551. void SendStop (MidiEvPtr e)
  552. {
  553.     MIDIPacket    TheMIDIPacket;
  554.     
  555.     TheMIDIPacket.flags = 0x80;    
  556.     TheMIDIPacket.len = 7;
  557.     TheMIDIPacket.data[0] = MStop;
  558.     MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
  559.     
  560.     MidiFreeEv(e);
  561. }
  562.  
  563.  
  564. void SendTune (MidiEvPtr e)
  565. {
  566.     MIDIPacket    TheMIDIPacket;
  567.     
  568.     TheMIDIPacket.flags = 0x80;    
  569.     TheMIDIPacket.len = 7;
  570.     TheMIDIPacket.data[0] = Tune;
  571.     MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
  572.     
  573.     MidiFreeEv(e);
  574. }
  575.  
  576.  
  577. void SendActiveSens (MidiEvPtr e)
  578. {
  579.     MIDIPacket    TheMIDIPacket;
  580.     
  581.     TheMIDIPacket.flags = 0x80;    
  582.     TheMIDIPacket.len = 7;
  583.     TheMIDIPacket.data[0] = ActSense;
  584.     MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
  585.     
  586.     MidiFreeEv(e);
  587. }
  588.  
  589.  
  590. void SendReset (MidiEvPtr e)
  591. {
  592.     MIDIPacket    TheMIDIPacket;
  593.     
  594.     TheMIDIPacket.flags = 0x80;    
  595.     TheMIDIPacket.len = 7;
  596.     TheMIDIPacket.data[0] = MReset;
  597.     MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
  598.     
  599.     MidiFreeEv(e);
  600. }
  601.  
  602.  
  603. void SendQuarterFrame (MidiEvPtr e)
  604. {
  605.     MIDIPacket    TheMIDIPacket;
  606.     
  607.     TheMIDIPacket.flags = 0x80;    
  608.     TheMIDIPacket.len = 8;
  609.     TheMIDIPacket.data[0] = QFrame;
  610.     TheMIDIPacket.data[1] = (Pitch(e) << 4) | Vel(e);
  611.     MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
  612.     
  613.     MidiFreeEv(e);
  614. }
  615.  
  616. void oldSendSysEx (MidiEvPtr e)
  617. {
  618.     MIDIPacket     TheMIDIPacket;
  619.     TScanner    s;
  620.     long        i;
  621.     
  622.     InitScanner(&s, e);
  623.     if (s.length <= 247) {
  624.     
  625.         TheMIDIPacket.flags = 0x80;    
  626.         TheMIDIPacket.len = s.length + 6 + 2;
  627.         TheMIDIPacket.data[0] = SysEx;
  628.         for (i=1; RemainToScan(&s); i++) TheMIDIPacket.data[i] = Scan(&s);
  629.         TheMIDIPacket.data[i] = EndSysX;
  630.         MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
  631.     }
  632.     
  633.     MidiFreeEv(e);
  634. }
  635.  
  636. void SendSysEx (MidiEvPtr e)
  637. {
  638.     TFormatter    f;
  639.     TScanner    s;
  640.     
  641.     InitScanner(&s, e);
  642.     InitFormat(&f, midiManagerRefOut[Port(e)]);
  643.     
  644.     Format(&f, SysEx);
  645.     while (RemainToScan(&s)) Format(&f, Scan(&s));
  646.     Format(&f, EndSysX);
  647.     StopFormat(&f);
  648.     
  649.     MidiFreeEv(e);
  650. }
  651.  
  652. void SendStream (MidiEvPtr e)
  653. {
  654.     TFormatter    f1, f2;
  655.     TScanner    s;
  656.     int            v;
  657.     short        p;
  658.     
  659.     p = midiManagerRefOut[Port(e)];
  660.     InitScanner(&s, e);
  661.     
  662.     for (v = Scan(&s); v >= 0;) {
  663.         if ( v == SysEx ) {
  664.             InitFormat(&f1, p);
  665.             Format(&f1, v);
  666.             for (v = Scan(&s); (v >= 0) && ((v < 128) || (v > EndSysX)) ; v = Scan(&s)) {
  667.                 if (v > EndSysX) {
  668.                     // message imbriqué
  669.                     InitFormat(&f2, p); Format(&f2, v); StopFormat(&f2);
  670.                 } else {
  671.                     Format(&f1, v);
  672.                 }
  673.             }
  674.             if (v == EndSysX) v = Scan(&s);
  675.             Format(&f1, EndSysX);
  676.             StopFormat(&f1);
  677.         }else if ((v >= NoteOff) && (v != EndSysX)) {
  678.             InitFormat(&f1, p);
  679.             Format(&f1, v);
  680.             for (v = Scan(&s); (v >= 0) && (v < 128); v = Scan(&s)) Format(&f1, v);
  681.             StopFormat(&f1);
  682.         }
  683.     }
  684.     
  685.     MidiFreeEv(e);
  686. }
  687.     
  688.  
  689. void InitMs2MMtbl (void)
  690. {
  691.     int    i;
  692.     
  693.     for (i = 0; i<256; i++) ms2mmtbl[i] = SendNothing;
  694.     ms2mmtbl[typeNote] = SendNote;
  695.     ms2mmtbl[typeKeyOn] = SendKeyOn;
  696.     ms2mmtbl[typeKeyOff] = SendKeyOff;
  697.     ms2mmtbl[typeKeyPress] = SendKeyPress;
  698.     ms2mmtbl[typeCtrlChange] = SendCtrlChange;
  699.     ms2mmtbl[typeProgChange] = SendProgChange;
  700.     ms2mmtbl[typeChanPress] = SendChanPress;
  701.     ms2mmtbl[typePitchWheel] = SendPitchWheel;
  702.     ms2mmtbl[typeSongPos] = SendSongPos;
  703.     ms2mmtbl[typeSongSel] = SendSongSel;
  704.     ms2mmtbl[typeClock] = SendClock;
  705.     ms2mmtbl[typeStart] = SendStart;
  706.     ms2mmtbl[typeContinue] = SendContinue;
  707.     ms2mmtbl[typeStop] = SendStop;
  708.     ms2mmtbl[typeTune] = SendTune;
  709.     ms2mmtbl[typeActiveSens] = SendActiveSens;
  710.     ms2mmtbl[typeReset] = SendReset;
  711.     ms2mmtbl[typeSysEx] = SendSysEx;
  712.     ms2mmtbl[typeStream] = SendStream;
  713.     ms2mmtbl[typeQuarterFrame] = SendQuarterFrame;
  714. }
  715.  
  716. /********************************************************************************/
  717. /*                                                                                 */
  718. /********************************************************************************/
  719.  
  720. void ReadKeyOff (MIDIPacket * m, short port, short chan)
  721. {
  722.     MidiEvPtr    e;
  723.     
  724.     if (e = MidiNewEv(typeKeyOff)) {
  725.         Port(e)    = port;
  726.         Chan(e)    = chan;
  727.         Pitch(e)= m->data[1];
  728.         Vel(e)    = m->data[2];
  729.         MidiSendIm(midiShareBridge, e);
  730.     }
  731. }
  732.  
  733. void ReadKeyOn (MIDIPacket * m, short port, short chan)
  734. {
  735.     MidiEvPtr    e;
  736.     
  737.     if (e = MidiNewEv(typeKeyOn)) {
  738.         Port(e)    = port;
  739.         Chan(e)    = chan;
  740.         Pitch(e)= m->data[1];
  741.         Vel(e)    = m->data[2];
  742.         MidiSendIm(midiShareBridge, e);
  743.     }
  744. }
  745.  
  746. void ReadKeyPress (MIDIPacket * m, short port, short chan)
  747. {
  748.     MidiEvPtr    e;
  749.     
  750.     if (e = MidiNewEv(typeKeyPress)) {
  751.         Port(e)    = port;
  752.         Chan(e)    = chan;
  753.         Pitch(e)= m->data[1];
  754.         Vel(e)    = m->data[2];
  755.         MidiSendIm(midiShareBridge, e);
  756.     }
  757. }
  758.  
  759. void ReadCtrlChange (MIDIPacket * m, short port, short chan)
  760. {
  761.     MidiEvPtr    e;
  762.     
  763.     if (e = MidiNewEv(typeCtrlChange)) {
  764.         Port(e)    = port;
  765.         Chan(e)    = chan;
  766.         Pitch(e)= m->data[1];
  767.         Vel(e)    = m->data[2];
  768.         MidiSendIm(midiShareBridge, e);
  769.     }
  770. }
  771.  
  772. void ReadProgChange (MIDIPacket * m, short port, short chan)
  773. {
  774.     MidiEvPtr    e;
  775.     
  776.     if (e = MidiNewEv(typeProgChange)) {
  777.         Port(e)    = port;
  778.         Chan(e)    = chan;
  779.         Pitch(e)= m->data[1];
  780.         MidiSendIm(midiShareBridge, e);
  781.     }
  782. }
  783.  
  784. void ReadChanPress (MIDIPacket * m, short port, short chan)
  785. {
  786.     MidiEvPtr    e;
  787.     
  788.     if (e = MidiNewEv(typeChanPress)) {
  789.         Port(e)    = port;
  790.         Chan(e)    = chan;
  791.         Pitch(e)= m->data[1];
  792.         MidiSendIm(midiShareBridge, e);
  793.     }
  794. }
  795.  
  796. void ReadPitchWheel (MIDIPacket * m, short port, short chan)
  797. {
  798.     MidiEvPtr    e;
  799.     
  800.     if (e = MidiNewEv(typePitchWheel)) {
  801.         Port(e)    = port;
  802.         Chan(e)    = chan;
  803.         Pitch(e)= m->data[1];
  804.         Vel(e)    = m->data[2];
  805.         MidiSendIm(midiShareBridge, e);
  806.     }
  807. }
  808.  
  809.  
  810. void ReadSmallSysEx (MIDIPacket * m, short port)
  811. {
  812.     MidiEvPtr    e;
  813.     int            i;
  814.     int            j;
  815.     
  816.     if (e = MidiNewEv(typeSysEx)) {
  817.         for (i=1, j=m->len-6; (i<j) && ( m->data[i] < 128 ); i++)
  818.             MidiAddField(e, m->data[i]);
  819.         Port(e)    = port;
  820.         Chan(e)    = 0;
  821.         MidiSendIm(midiShareBridge, e);
  822.     }
  823. }
  824.  
  825. void ReadStartCont (MIDIPacket * m, short port)
  826. {    
  827.     MidiEvPtr     e;
  828.     int            i,j;
  829.  
  830.     if (e = PendingEv[port]) {
  831.         MidiFreeEv(e);
  832.         e = nil;
  833.     }
  834.     if (m->data[0] == SysEx) {
  835.         if (e = MidiNewEv(typeSysEx)) {
  836.             for (i=1, j=m->len-6; (i<j) && ( m->data[i] < 128 ); i++)
  837.                 MidiAddField(e, m->data[i]);
  838.             Port(e)    = port;
  839.             Chan(e)    = 0;
  840.         }
  841.     } else {
  842.         if (e = MidiNewEv(typeStream)) {
  843.             for (i=0, j=m->len-6; i<j; i++) MidiAddField(e, m->data[i]);
  844.             Port(e)    = port;
  845.             Chan(e)    = 0;
  846.         }
  847.     }
  848.     PendingEv[port] = e;
  849. }        
  850.  
  851. void ReadMidCont (MIDIPacket * m, short port)
  852. {    
  853.     MidiEvPtr     e;
  854.     int            i,j;
  855.  
  856.     if (e = PendingEv[port]) {
  857.         if (EvType(e) == typeSysEx) {
  858.             for (i=0, j=m->len-6; (i<j) && ( m->data[i] < 128 ); i++)
  859.                 MidiAddField(e, m->data[i]);
  860.         } else if (EvType(e) == typeStream) {
  861.             for (i=0, j=m->len-6; i<j; i++)
  862.                 MidiAddField(e, m->data[i]);
  863.         }
  864.     }
  865. }        
  866.  
  867. void ReadEndCont (MIDIPacket * m, short port)
  868. {    
  869.     MidiEvPtr     e;
  870.     int            i,j;
  871.  
  872.     if (e = PendingEv[port]) {
  873.         if (EvType(e) == typeSysEx) {
  874.             for (i=0, j=m->len-6; (i<j) && ( m->data[i] < 128 ); i++)
  875.                 MidiAddField(e, m->data[i]);
  876.         } else if (EvType(e) == typeStream) {
  877.             for (i=0, j=m->len-6; i<j; i++)
  878.                 MidiAddField(e, m->data[i]);
  879.         }
  880.         MidiSendIm(midiShareBridge, e);
  881.         PendingEv[port] = nil;
  882.     }
  883. }        
  884.         
  885.  
  886. void ReadQuarterFrame (MIDIPacket * m, short port)
  887. {
  888.     MidiEvPtr    e;
  889.     
  890.     if (e = MidiNewEv(typeQuarterFrame)) {
  891.         Port(e)    = port;
  892.         Chan(e)    = 0;
  893.         Pitch(e)= m->data[1] >> 4;
  894.         Vel(e)    = m->data[1] & 0xF;
  895.         MidiSendIm(midiShareBridge, e);
  896.     }
  897. }
  898.  
  899. void ReadSongPos (MIDIPacket * m, short port)
  900. {
  901.     MidiEvPtr    e;
  902.     
  903.     if (e = MidiNewEv(typeSongPos)) {
  904.         Port(e)    = port;
  905.         Chan(e)    = 0;
  906.         Pitch(e)= m->data[1];
  907.         Vel(e)    = m->data[2];
  908.         MidiSendIm(midiShareBridge, e);
  909.     }
  910. }
  911.  
  912. void ReadSongSel (MIDIPacket * m, short port)
  913. {
  914.     MidiEvPtr    e;
  915.     
  916.     if (e = MidiNewEv(typeSongSel)) {
  917.         Port(e)    = port;
  918.         Chan(e)    = 0;
  919.         Pitch(e)= m->data[1];
  920.         MidiSendIm(midiShareBridge, e);
  921.     }
  922. }
  923.  
  924. void ReadClock (MIDIPacket *, short port)
  925. {
  926.     MidiEvPtr    e;
  927.     
  928.     if (e = MidiNewEv(typeClock)) {
  929.         Port(e)    = port;
  930.         Chan(e)    = 0;
  931.         MidiSendIm(midiShareBridge, e);
  932.     }
  933. }
  934.  
  935. void ReadStart (MIDIPacket *, short port)
  936. {
  937.     MidiEvPtr    e;
  938.     
  939.     if (e = MidiNewEv(typeStart)) {
  940.         Port(e)    = port;
  941.         Chan(e)    = 0;
  942.         MidiSendIm(midiShareBridge, e);
  943.     }
  944. }
  945.  
  946. void ReadContinue (MIDIPacket *, short port)
  947. {
  948.     MidiEvPtr    e;
  949.     
  950.     if (e = MidiNewEv(typeContinue)) {
  951.         Port(e)    = port;
  952.         Chan(e)    = 0;
  953.         MidiSendIm(midiShareBridge, e);
  954.     }
  955. }
  956.  
  957. void ReadStop (MIDIPacket *, short port)
  958. {
  959.     MidiEvPtr    e;
  960.     
  961.     if (e = MidiNewEv(typeStop)) {
  962.         Port(e)    = port;
  963.         Chan(e)    = 0;
  964.         MidiSendIm(midiShareBridge, e);
  965.     }
  966. }
  967.  
  968. void ReadTune (MIDIPacket *, short port)
  969. {
  970.     MidiEvPtr    e;
  971.     
  972.     if (e = MidiNewEv(typeTune)) {
  973.         Port(e)    = port;
  974.         Chan(e)    = 0;
  975.         MidiSendIm(midiShareBridge, e);
  976.     }
  977. }
  978.  
  979. void ReadActiveSens (MIDIPacket *, short port)
  980. {
  981.     MidiEvPtr    e;
  982.     
  983.     if (e = MidiNewEv(typeActiveSens)) {
  984.         Port(e)    = port;
  985.         Chan(e)    = 0;
  986.         MidiSendIm(midiShareBridge, e);
  987.     }
  988. }
  989.  
  990. void ReadReset (MIDIPacket *, short port)
  991. {
  992.     MidiEvPtr    e;
  993.     
  994.     if (e = MidiNewEv(typeReset)) {
  995.         Port(e)    = port;
  996.         Chan(e)    = 0;
  997.         MidiSendIm(midiShareBridge, e);
  998.     }
  999. }
  1000.  
  1001. void ReadUndef (MIDIPacket *, short)
  1002. {
  1003. }
  1004.  
  1005. void ReadNonChan (MIDIPacket * m, short port, short chan)
  1006. {
  1007.     (*rt2mstbl[chan])(m, port);
  1008. }
  1009.  
  1010. void initmm2mstbl(void)
  1011. {
  1012.  
  1013. // table principale
  1014.     mm2mstbl[0] = ReadKeyOff;
  1015.     mm2mstbl[1] = ReadKeyOn;
  1016.     mm2mstbl[2] = ReadKeyPress;
  1017.     mm2mstbl[3] = ReadCtrlChange;
  1018.     mm2mstbl[4] = ReadProgChange;
  1019.     mm2mstbl[5] = ReadChanPress;
  1020.     mm2mstbl[6] = ReadPitchWheel;
  1021.     mm2mstbl[7] = ReadNonChan;
  1022.     
  1023. // table secondaire pour les messages sans canaux
  1024.     rt2mstbl[0] = ReadSmallSysEx;
  1025.     rt2mstbl[1] = ReadQuarterFrame;
  1026.     rt2mstbl[2] = ReadSongPos;
  1027.     rt2mstbl[3] = ReadSongSel;
  1028.     rt2mstbl[4] = ReadUndef;
  1029.     rt2mstbl[5] = ReadUndef;
  1030.     rt2mstbl[6] = ReadTune;
  1031.     rt2mstbl[7] = ReadUndef; // end of sysex
  1032.     rt2mstbl[8] = ReadClock;
  1033.     rt2mstbl[9] = ReadUndef;
  1034.     rt2mstbl[10] = ReadStart;
  1035.     rt2mstbl[11] = ReadContinue;
  1036.     rt2mstbl[12] = ReadStop;
  1037.     rt2mstbl[13] = ReadUndef;
  1038.     rt2mstbl[14] = ReadActiveSens;
  1039.     rt2mstbl[15] = ReadReset;
  1040. }
  1041.         
  1042.  
  1043. void ReadMessage (MIDIPacket * m, short port)
  1044. {
  1045.     unsigned char status;
  1046.     
  1047.     
  1048.     if (((m->flags) & midiContMask) == midiNoCont) {
  1049.         status = m->data[0];
  1050.         if (status >= NoteOff)
  1051.             (*mm2mstbl[(status >> 4) & 7])(m, port, status & 0xF);
  1052.     } else if (((m->flags) & midiContMask) == midiStartCont) {
  1053.         ReadStartCont(m, port);
  1054.     } else if (((m->flags) & midiContMask) == midiMidCont) {
  1055.         ReadMidCont(m, port);
  1056.     } else if (((m->flags) & midiContMask) == midiEndCont) {
  1057.         ReadEndCont(m, port);
  1058.     }
  1059. }
  1060.  
  1061. pascal short mmReader0 (MIDIPacket * m, long myA5)
  1062. {
  1063.     long    sysA5 = SetA5(myA5);
  1064.     
  1065.     if (((m->flags) & midiTypeMask) == midiMsgType)
  1066.         ReadMessage(m, 0);
  1067.     SetA5(sysA5);
  1068.     return midiMorePacket;
  1069. }
  1070.  
  1071.  
  1072. pascal short mmReader1 (MIDIPacket * m, long myA5)
  1073. {
  1074.     long    sysA5 = SetA5(myA5);
  1075.     
  1076.     if (((m->flags) & midiTypeMask) == midiMsgType)
  1077.         ReadMessage(m, 1);
  1078.     SetA5(sysA5);
  1079.     return midiMorePacket;
  1080. }
  1081.  
  1082.  
  1083. /********************************************************************************/
  1084. /*                                 MidiManager Part                                */
  1085. /********************************************************************************/
  1086.  
  1087.  
  1088. void CloseMidiManager (void)
  1089. {
  1090.     MIDISignOut(appID);
  1091. }
  1092.  
  1093.  
  1094. Boolean SetUpMidiManager (void)
  1095. {
  1096.     MIDIPortParams    pparams;                // MIDI Mgr pparams data structure
  1097.     Handle            icon;
  1098.     OSErr            err;
  1099.  
  1100.     
  1101. // Sign in into MidiManager
  1102.  
  1103.     icon = GetResource('ICN#', 128);
  1104.     err = MIDISignIn(appID, 0L, icon, appName);
  1105.     if (err) return false;
  1106.     
  1107.     
  1108. // Add a time port.
  1109.  
  1110.     pparams.portID = 'time';
  1111.     pparams.portType = midiPortTypeTimeInv;  // le port est invisible
  1112.     pparams.timeBase = NULL;
  1113.     pparams.readHook = NULL;
  1114.     pparams.initClock.sync = midiInternalSync;
  1115.     pparams.initClock.curTime = 0;
  1116.     pparams.initClock.format = midiFormatMSec;
  1117.     pparams.refCon = NULL;
  1118.     myC2PStr("TimeBase", pparams.name);
  1119.     
  1120.     (void) MIDIAddPort(appID, timePortBuffSize, &midiManagerTime, &pparams);
  1121.     
  1122.     
  1123. // Add input port 0.
  1124.  
  1125.     pparams.portID = 'in 0';
  1126.     pparams.portType = midiPortTypeInput;
  1127.     pparams.timeBase = midiManagerTime;
  1128.     pparams.offsetTime = midiGetCurrent;
  1129.     pparams.readHook = (Ptr)mmReader0;
  1130.     pparams.refCon = SetCurrentA5();
  1131.     myC2PStr("In0", pparams.name);
  1132.     
  1133.     (void) MIDIAddPort(appID, inputPortBuffSize, &midiManagerRefIn[0], &pparams);
  1134.     
  1135.     
  1136. // Add input port 1.
  1137.  
  1138.     pparams.portID = 'in 1';
  1139.     pparams.portType = midiPortTypeInput;
  1140.     pparams.timeBase = midiManagerTime;
  1141.     pparams.offsetTime = midiGetCurrent;
  1142.     pparams.readHook = (Ptr)mmReader1;
  1143.     pparams.refCon = SetCurrentA5();
  1144.     myC2PStr("In1", pparams.name);
  1145.     
  1146.     (void) MIDIAddPort(appID, inputPortBuffSize, &midiManagerRefIn[1], &pparams);
  1147.  
  1148.  
  1149. // Add output port 0.
  1150.  
  1151.     pparams.portID = 'out0';
  1152.     pparams.portType = midiPortTypeOutput;
  1153.     pparams.timeBase = midiManagerTime;
  1154.     pparams.offsetTime = midiGetCurrent;
  1155.     pparams.readHook = NULL;
  1156.     pparams.refCon = NULL;
  1157.     myC2PStr("Out0", pparams.name);
  1158.     
  1159.     (void) MIDIAddPort(appID, outputPortBuffSize, &midiManagerRefOut[0], &pparams);
  1160.  
  1161.     
  1162. // Add output port 1.
  1163.  
  1164.     pparams.portID = 'out1';
  1165.     pparams.portType = midiPortTypeOutput;
  1166.     pparams.timeBase = midiManagerTime;
  1167.     pparams.offsetTime = midiGetCurrent;
  1168.     pparams.readHook = NULL;
  1169.     pparams.refCon = NULL;
  1170.     myC2PStr("Out1", pparams.name);
  1171.     
  1172.     (void) MIDIAddPort(appID, outputPortBuffSize, &midiManagerRefOut[1], &pparams);
  1173.  
  1174.  
  1175. // Start our Clock.
  1176.  
  1177.     MIDIStartTime(midiManagerTime);
  1178.     initmm2mstbl();
  1179.     
  1180.     return true;
  1181. }
  1182.  
  1183. /********************************************************************************/
  1184. /*                                     MidiShare Part                                */
  1185. /********************************************************************************/
  1186.  
  1187. pascal void TransferEventsToMidiManager (short r)
  1188. {
  1189.     MidiEvPtr    e;
  1190.     
  1191.     while (e = MidiGetEv(r)) {
  1192.         (*ms2mmtbl[e->evType])(e);
  1193.     }
  1194. }
  1195.  
  1196.  
  1197. void InstallFilter ()
  1198. {
  1199.     register short i;
  1200.  
  1201.     for (i = 0; i<256; i++)
  1202.     {                                         
  1203.         AcceptBit(myFilter.evType,i);                /* accepte tous les types d'événements    */
  1204.         RejectBit(myFilter.port,i);                    /* refuse tous les ports                */
  1205.     }
  1206.     AcceptBit(myFilter.port,0);                        /* accept le port 0                        */
  1207.     AcceptBit(myFilter.port,1);                        /* accept le port 1                        */
  1208.                                             
  1209.     for (i = 0; i<16; i++)
  1210.         AcceptBit(myFilter.channel,i);                /* et sur tous les canaux Midi            */
  1211.         
  1212.     MidiSetFilter( midiShareBridge, &myFilter );       /* installe le filtre                    */
  1213. }
  1214.  
  1215. /********************************************************************************/
  1216. /*                                 Receiving to Smalltalk                            */
  1217. /********************************************************************************/
  1218.  
  1219. TFilter        receiveFilter;
  1220.  
  1221.  
  1222. void InstallReceiveFilter ( short ref )
  1223. {
  1224.     register short i;
  1225.  
  1226.     for (i = 0; i < 256; i++) {
  1227.         RejectBit(receiveFilter.evType,i);                  
  1228.         RejectBit(receiveFilter.port,i);                          
  1229.     }                                          
  1230.     for (i = 0; i < 8;  i++) AcceptBit(receiveFilter.port,i);                                    
  1231.     for (i = 0; i < 16; i++) AcceptBit(receiveFilter.channel,i);          
  1232.     
  1233.     AcceptBit(receiveFilter.evType,typeNote);
  1234.     AcceptBit(receiveFilter.evType,typeKeyOn);
  1235.     AcceptBit(receiveFilter.evType,typeKeyOff);
  1236.     AcceptBit(receiveFilter.evType,typeCtrlChange);
  1237.     AcceptBit(receiveFilter.evType,typeProgChange);
  1238.     
  1239.     MidiSetFilter( ref, &receiveFilter );         
  1240. }
  1241.  
  1242. void UPMidiGetEvent ( upHandle rcvr )
  1243. {
  1244.     upHandle answer;
  1245.     MidiEvPtr e;
  1246.     
  1247.     if (e = MidiGetEv(midiShareRef)) {
  1248.         answer = UPallocByteArray((upByte)0,(upInt)sizeof(TMidiEv));
  1249.         (void)UPcopyCtoSTbytes(answer,e,(upInt)sizeof(TMidiEv),1L);
  1250.         MidiFreeEv(e);
  1251.         UPreturnHandle(answer);
  1252.     }
  1253.     else UPreturnNil();
  1254. }
  1255.  
  1256.  
  1257. void UPMidiClearEvents ( upHandle rcvr )
  1258. {
  1259.     MidiFlushEvs(midiShareRef);
  1260.     UPreturnTrue();
  1261. }
  1262.  
  1263.  
  1264. /********************************************************************************/
  1265. /*                                 MidiManager Bridge                                */
  1266. /********************************************************************************/
  1267.  
  1268. Boolean MidiManager () 
  1269.     return true;
  1270. }
  1271.  
  1272.  
  1273. Boolean MidiBridgeOpen ()
  1274. {
  1275.     if (bridgeInstalled) MidiBridgeClose();
  1276.     
  1277.     bridgeInstalled = false;
  1278.     
  1279.     if (!MidiManager()) return false;
  1280.     
  1281.     if ((midiShareBridge = MidiOpen(midiShareBridgeName)) == MIDIerrSpace) 
  1282.         return false;
  1283.         
  1284.     if ((midiShareLink = MidiOpen(midiShareLinkName))  == MIDIerrSpace) {
  1285.         MidiClose(midiShareBridge);
  1286.         return false;
  1287.     };
  1288.     
  1289.     InstallFilter();                            
  1290.     InitMs2MMtbl();
  1291.     
  1292.     if (!SetUpMidiManager()) {
  1293.         MidiClose(midiShareBridge);
  1294.         MidiClose(midiShareLink);
  1295.         return false;
  1296.     };
  1297.     
  1298.     MidiSetRcvAlarm(midiShareBridge, TransferEventsToMidiManager);
  1299.     MidiConnect(midiShareLink, midiShareBridge, true);
  1300.     
  1301.     bridgeInstalled = true;
  1302.     return true;
  1303. }
  1304.  
  1305.  
  1306. Boolean MidiBridgeClose ()
  1307. {    
  1308.     if (!bridgeInstalled) return false;
  1309.     
  1310.     bridgeInstalled = false;
  1311.     
  1312.     MIDISignOut(appID);
  1313.     MidiClose(midiShareLink);
  1314.     MidiClose(midiShareBridge);                
  1315.         
  1316.     return true;
  1317. }
  1318.  
  1319.  
  1320. /********************************************************************************/
  1321. /*                                 Opening/Closing                                    */
  1322. /********************************************************************************/
  1323.  
  1324. Boolean MidiSystemOpen ()
  1325. {    
  1326.     if (!MidiShare()) return false;    
  1327.     if ((midiShareRef  = MidiOpen(midiShareRefName)) == MIDIerrSpace) return false;    
  1328.     
  1329.     MidiConnect(midiShareRef, 0, true);                 // physical output
  1330.     MidiConnect(0, midiShareRef, true);                    // physical input
  1331.     InstallReceiveFilter(midiShareRef);                    // filter out events useless for Leviathan
  1332.     
  1333.     if (MidiManager()) MidiBridgeOpen();
  1334.     OpenSequencer();
  1335.     return true;
  1336. }
  1337.  
  1338. Boolean MidiSystemClose ()
  1339. {
  1340.     if (!MidiShare()) return false;
  1341.     
  1342.     CloseSequencer();
  1343.     MidiClose(midiShareRef);
  1344.     if (MidiManager()) MidiBridgeClose();
  1345.     
  1346.     return true;
  1347. }
  1348.  
  1349. Boolean MidiSystemStop ()
  1350. {    
  1351.     if (!MidiShare()) return false;
  1352.     
  1353.     StopSequencer();
  1354.     return true;
  1355. }
  1356.  
  1357. /********************************************************************************/
  1358. /*                                 User Primitives                                    */
  1359. /********************************************************************************/
  1360.  
  1361. void UPMidiSharePresent ( upHandle rcvr ) { UPreturnHandle( UPCtoSTbool( MidiShare()));}
  1362. void UPMidiGetVersion     ( upHandle rcvr ) { UPreturnHandle( UPCtoSTint( MidiGetVersion()));}
  1363. void UPMidiOpen         ( upHandle rcvr ) {    UPreturnHandle( UPCtoSTbool( MidiSystemOpen()));}
  1364. void UPMidiClose         ( upHandle rcvr ) { UPreturnHandle( UPCtoSTbool( MidiSystemClose()));}
  1365. void UPMidiStart         ( upHandle rcvr ) { UPreturnHandle( UPCtoSTbool( StartSequencer()));}
  1366. void UPMidiStop         ( upHandle rcvr ) { UPreturnHandle( UPCtoSTbool( MidiSystemStop()));}
  1367. void UPMidiGetTime         ( upHandle rcvr ) { UPreturnHandle( UPCtoSTint( MidiGetTime()));}
  1368. void UPMidiGetClock     ( upHandle rcvr ) { UPreturnHandle( UPCtoSTint( ticks(MidiGetTime())));}
  1369. void UPMidiGetTotalSpace ( upHandle rcvr ){ UPreturnHandle( UPCtoSTint( MidiTotalSpace()));}
  1370. void UPMidiGetFreeSpace ( upHandle rcvr ) { UPreturnHandle( UPCtoSTint( MidiFreeSpace()));}
  1371.  
  1372.  
  1373. void UPMidiSetTiming ( 
  1374.     upHandle rcvr, 
  1375.     upHandle startInteger,
  1376.     upHandle tempoInteger,
  1377.     upHandle resolutionInteger,
  1378.     upHandle delayInteger )
  1379. {
  1380.     StopSequencer();
  1381.     
  1382.     offset = MidiGetTime() + UPSTtoCint( delayInteger );
  1383.     start = UPSTtoCint( startInteger );
  1384.     tempo = UPSTtoCint( tempoInteger );
  1385.     resolution = UPSTtoCint( resolutionInteger );
  1386.     UPreturnHandle(UPCtoSTint(0));
  1387. }
  1388.  
  1389.  
  1390. /********************************************************************************/
  1391. /*                                 CONVERTING TIME (ms/ticks)                        */
  1392. /********************************************************************************/
  1393.  
  1394. long ms ( long ticks )
  1395. {
  1396.     return 240000.0 * ticks / (tempo * resolution);
  1397. }
  1398.  
  1399. long ticks ( long ms )
  1400. {
  1401.     return (ms * tempo * resolution) / 240000.0;
  1402. }
  1403.  
  1404. /********************************************************************************/
  1405. /*                                 SENDING EVENTS                                    */
  1406. /********************************************************************************/
  1407.  
  1408.  
  1409. void Sequence ( MidiEvPtr e )
  1410. {
  1411.     MidiAddSeq(sequence,e);
  1412. }
  1413.  
  1414.  
  1415. void SendNow ( MidiEvPtr e )
  1416. {
  1417.     if ( Port(e) == midiManagerPort0) {
  1418.             Port(e) = 0;
  1419.             MidiSendIm(midiShareLink,e);
  1420.             return;
  1421.     }
  1422.     
  1423.     if ( Port(e) == midiManagerPort1 ) {
  1424.             Port(e) = 1;
  1425.             MidiSendIm(midiShareLink,e);
  1426.             return;
  1427.     }
  1428.     
  1429.     MidiSendIm(midiShareRef,e); 
  1430. }
  1431.  
  1432.  
  1433. void Send ( MidiEvPtr e )
  1434. {
  1435.     if ( Port(e) == midiManagerPort0) {
  1436.             Port(e) = 0;
  1437.             MidiSend(midiShareLink,e);
  1438.             return;
  1439.     }
  1440.     
  1441.     if ( Port(e) == midiManagerPort1 ) {
  1442.             Port(e) = 1;
  1443.             MidiSend(midiShareLink,e);
  1444.             return;
  1445.     }
  1446.     
  1447.     MidiSend(midiShareRef,e); 
  1448. }
  1449.  
  1450.  
  1451.  
  1452. void SendNoteEvent ( 
  1453.     long date, 
  1454.     int port, 
  1455.     int chan, 
  1456.     int pitch, 
  1457.     int vel, 
  1458.     int dur)
  1459. {
  1460.     MidiEvPtr e;
  1461.     
  1462.     if (e = MidiNewEv(typeNote)) {                    
  1463.         Date(e) = date;
  1464.         Chan(e) = chan;
  1465.         Port(e) = port;
  1466.         Pitch(e) = pitch;
  1467.         Vel(e) = vel;
  1468.         Dur(e) = ms(dur);
  1469.  
  1470.         Sequence(e);
  1471.     }
  1472. }
  1473.  
  1474. void SendControlEvent ( 
  1475.     long date, 
  1476.     int port, 
  1477.     int chan, 
  1478.     int controller, 
  1479.     int value)
  1480. {
  1481.     MidiEvPtr e;
  1482.     
  1483.     if (e = MidiNewEv(typeCtrlChange)) {                    
  1484.         Date(e) = date;
  1485.         Chan(e) = chan;
  1486.         Port(e) = port;
  1487.         MidiSetField(e,0,controller);    
  1488.         MidiSetField(e,1,value);
  1489.         
  1490.         Sequence(e);
  1491.     }
  1492. }
  1493.  
  1494. void SendAllNotesOff ( 
  1495.     long date, 
  1496.     int port, 
  1497.     int chan)
  1498. {
  1499.     MidiEvPtr e;
  1500.     register int pitch;
  1501.     
  1502.     for (pitch = 0; pitch < 127; pitch++) {
  1503.         if (e = MidiNewEv(typeKeyOff)) {                    
  1504.             Date(e) = date;
  1505.             Chan(e) = chan;
  1506.             Port(e) = port;
  1507.             Pitch(e) = pitch;
  1508.         
  1509.             Send(e);
  1510.         }
  1511.     }
  1512. }
  1513.  
  1514.  
  1515. void SendProgramEvent ( 
  1516.     long date, 
  1517.     int port, 
  1518.     int chan, 
  1519.     int program)
  1520. {
  1521.     MidiEvPtr e;
  1522.     
  1523.     if (e = MidiNewEv(typeProgChange)) {                    
  1524.         Date(e) = date;
  1525.         Chan(e) = chan;
  1526.         Port(e) = port;
  1527.         MidiSetField(e,0,program);
  1528.         
  1529.         Sequence(e);
  1530.     }
  1531. }
  1532.  
  1533.  
  1534. void UPMidiSendEvent ( 
  1535.     upHandle rcvr, 
  1536.     upHandle clock, 
  1537.     upHandle port, 
  1538.     upHandle chan, 
  1539.     upHandle type, 
  1540.     upHandle data1, /* pitch, controller no., program no. */ 
  1541.     upHandle data2, /* velocity, controller value */
  1542.     upHandle data3  /* duration */ )
  1543. {
  1544.     long date;
  1545.     
  1546.     date = offset + ms(UPSTtoCint(clock) - start);
  1547.     
  1548.     switch (UPSTtoCint(type)) {
  1549.     
  1550.         case typeNote:
  1551.             SendNoteEvent(
  1552.                 date, 
  1553.                 UPSTtoCint(port), 
  1554.                 UPSTtoCint(chan), 
  1555.                 UPSTtoCint(data1), 
  1556.                 UPSTtoCint(data2), 
  1557.                 UPSTtoCint(data3));
  1558.             break;
  1559.             
  1560.         case typeCtrlChange:
  1561.             SendControlEvent(
  1562.                 date, 
  1563.                 UPSTtoCint(port), 
  1564.                 UPSTtoCint(chan), 
  1565.                 UPSTtoCint(data1), 
  1566.                 UPSTtoCint(data2));
  1567.             break;    
  1568.             
  1569.         case typeProgChange:
  1570.             SendProgramEvent(
  1571.                 date, 
  1572.                 UPSTtoCint(port), 
  1573.                 UPSTtoCint(chan), 
  1574.                 UPSTtoCint(data1));
  1575.             break;                
  1576.     };
  1577.     
  1578.     UPreturnHandle(rcvr);
  1579. }
  1580.  
  1581.  
  1582.  
  1583.  
  1584. /********************************************************************************/
  1585. /*                         USER PRIMITIVES INSTALLATION                            */
  1586. /********************************************************************************/
  1587.  
  1588.  
  1589. char* UPinstall()
  1590. {
  1591.     UPaddPrimitive(11001, UPMidiSharePresent, 0);
  1592.     UPaddPrimitive(11002, UPMidiGetVersion, 0);
  1593.     UPaddPrimitive(11003, UPMidiOpen, 0);
  1594.     UPaddPrimitive(11004, UPMidiClose, 0);
  1595.     UPaddPrimitive(11005, UPMidiGetTime, 0);
  1596.     UPaddPrimitive(11015, UPMidiGetClock, 0);
  1597.     
  1598.     UPaddPrimitive(11006, UPMidiSendEvent, 7);
  1599.     
  1600.     UPaddPrimitive(11020, UPMidiGetTotalSpace, 0);
  1601.     UPaddPrimitive(11021, UPMidiGetFreeSpace, 0);
  1602.     UPaddPrimitive(11022, UPMidiSetTiming, 4);
  1603.     
  1604.     UPaddPrimitive(11030, UPMidiStop, 0);
  1605.     UPaddPrimitive(11031, UPMidiStart, 0);
  1606.     
  1607.     UPaddPrimitive(11042, UPMidiGetEvent, 0);
  1608.     UPaddPrimitive(11043, UPMidiClearEvents, 0);
  1609.     
  1610.     return "MidiShare User Primitives";
  1611. }
  1612.  
  1613. char *versionString =
  1614.     "Objectworks\\Smalltalk(R) Release 4.1\nwith MidiShare™ Interface";
  1615.  
  1616. char *resourceClassName = "St80";
  1617.  
  1618.  
  1619.  
  1620. /*
  1621.  * UPInitLinkRegistry
  1622.  *
  1623.  * All statically linked procedures accessible to
  1624.  * the Objectkit Smalltalk C Programming kit
  1625.  * must be defined in this function using
  1626.  * UPRegisterSymbolAndHandle(char *, void *).
  1627.  */
  1628.  
  1629. void
  1630. UPInitLinkRegistry()
  1631. {
  1632. }
  1633.  
  1634.  
  1635. main(argc, argv)
  1636.     int argc;
  1637.     char *argv[];
  1638. {
  1639.     return st80Main(argc, argv, (char **)0);
  1640. }
  1641.